那今天來講溝通協作的部份,就是文件。不過這邊的的文件,指的並不是 PM 在撰寫的需求文件。而是 RD 常會面臨到的 Coding Document。
如果你的程式碼易讀並加上適當的標記,透過工具應該可以產生出可讀的文件,javadoc 就是這麼個邏輯。不過前提當然是你的程式真的要易讀然後標記到位,哈哈。
而除了這種 Coding Document 之外,因應 Microservice 紅到你不要不要的今天。今天其實我是要講 REST Doc 的。
也就是身為後端你不可以能不做的日常生活,開 API。最常見是的 RESTFul 風格,也就是 HTTP,當然我也是挺推薦 gRPC 但我跟他還沒熟到可以跟大家介紹,哈哈。
做為這樣一件跟喝水吃飯一樣簡單的事情,如何開的好?首先當然是你的設計頂呱呱一級棒,不用文件也能讓人家秒懂,但我們都知道你被時程追殺的前提下,這個在現實發生的機率是 9.487% 吧。那好吧,只好來寫寫文件幫助人家了解,丟給別的部門自己看自己接,還可以塞客戶的嘴,簡直是居家旅行,殺人滅口,必備良藥 (又是星爺梗!?)
好的準備進入正題,今天要講的 API 文件是 Postman Doc、Swagger 和 Spring REST Docs。
你沒看錯,postman 有 document 的功能,其實他隱藏的功能很多,好不好用其次,只是大家多半用來當做 http client。他還可以寫測試、產生 client 端程式碼、錄製請求與回應、產生文件。細部的操作其實谷哥大神都找的到,我這邊就放一張截圖讓大家聞香一下。
J葛就狂了,設計良好,畫面優美,自帶 client 端,透過 yaml 定義。有興趣的可以去這個連結玩一玩 Swagger Editor,我下面放一張截圖。
這個東西一樣有延伸的 client generator,目前是幾乎涵蓋各個語言。依照敝公司的作法就是,後端會生成這個 swagger doc,前端會用工具去產生調用 api 的程式碼,保持一致性,也省下不必要的工。
另外如果延伸進入各語言的話,畢竟其實我們不大可能特別去記辣個 swagger yaml 怎麼寫。所以在 Spring 我們是會用一個叫做 SpringFox 的套件,他會自己去抓你 Spring MVC 的 Annotation,另外你也可以自行加上ㄧ些 Annotation 幫助產出文件。我大春天真是很威武,什麼都有,什麼都不奇怪。
最後一個來講 Spring REST Docs,看到名字你就要知道這個跟 Spring 有關。他產出來的文件是靜態的 .adoc。就是傳說中的 AsciiDoc,我個人覺得用來印刷很優美,事實上如果你要交付給客戶這個應該會比 Swagger 更好。而且 AsciiDoc 在語法上也比 Markdown 更豐富,可以表達的更到位,我們這邊先來看一張他的圖。
好,既然是 Spring 出品總不可能只有這樣吧?對,你說對了,他還有另外一個特色是 Test driven documentation of your REST API,TDD 信徒看到這個一定開心到歪掉,寫測試的時候順便寫文件!?不知道設計者怎麼想的,但真的是絕佳的一手!我們這邊直接來借用網路上的範例。
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
@AutoConfigureRestDocs(Constant.API_DOCUMENT_SNIPPETS_DIR)
public class UserControllerTests {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
private final ConstraintDescriptions userConstraints = new ConstraintDescriptions(User.class);
@Test
public void findUserSuccess() throws Exception {
given(userService.findUser("10000")).willReturn(new User("jackson", 12, 10000));
mockMvc.perform(get("/user")
.param("id", "10000"))
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andDo(document("user-find",
requestParameters(
parameterWithName("id").description("用户id")
),
responseFields(
fieldWithPath("id").description("用户id"),
fieldWithPath("name").description("用户名"),
fieldWithPath("age").description("年龄")
)
)
);
verify(userService).findUser(anyString());
}
}
可以編寫測試編寫文件真是太酷,你看看人家都幫你減少負擔了還不趕快去寫測試R,嘿嘿。
About Me
Jian-Min Huang
wide range skill set backend engineer
Research, Architecture, Coding, DB, Ops, Infra.
mainly write Java but also ❤️ Scala, Kotlin and Go